/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.base.controller;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.converter.DictConverter;
import com.xy.biz.base.domain.dto.DictDTO;
import com.xy.biz.base.domain.dto.DictPropertyDTO;
import com.xy.biz.base.domain.query.DictQuery;
import com.xy.biz.base.domain.req.*;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.base.service.DictService;
import com.xy.biz.base.service.impl.DictInitialize;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.StringKeyValue;
import com.xy.lang.domain.treeing.Tree;
import com.xy.lang.domain.treeing.TreeItem;
import com.xy.lang.validation.SaveChecks;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import io.swagger.annotations.Api;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;

/**
 *
 *
 * @author zsp
 * @date 2020-5-23
 */
@Api(tags = "字典服务")
@Slf4j
@RestController
@RequestMapping("/api/base/dict")
public class DictController implements DictClient {

    @Autowired
    private DictService dictService;
    @Autowired
    private DictInitialize dictInitialize;

    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save")
    public Result<?> saveDict(@RequestBody SaveDictRequest request) {
        return dictService.saveDict(request);
    }

    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_auto_code")
    @Override
    public Result<?> saveDictAutoCode(@RequestBody SaveDictRequest request) {
        return dictService.saveDict(request);
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update_dict_name")
    public Result<?> updateDictName(@RequestBody UpdateDictRequest request) {
        return dictService.updateDictName(request);
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update")
    @Override
    public Result<?> updateDict(@RequestBody SaveDictRequest request) {
        return dictService.updateDict(request);
    }

    @Override
    @PostMapping(value = "/update_all")
    public Result<?> updateAll(@RequestBody UpdateDictAllRequest request) {
        return dictService.updateAll(request);
    }

    @Override
    @Validatable
    @PostMapping(value = "/delete")
    public Result<?> deleteDict(@RequestBody GetDictRequest request) {
        return dictService.deleteDict(request.getDictId());
    }

    @Override
    @Validatable
    @PostMapping(value = "/delete dict no verify")
    public Result<?> deleteDictNoVerify(@RequestBody GetDictRequest request) {
        return dictService.deleteDictNoVerify(request.getDictId());
    }

    @Override
    @Validatable
    @PostMapping(value = "/get")
    public Result<DictDTO> getDict(@RequestBody GetDictRequest request) {
        return Result.success(DictConverter.toDTO(dictService.getDict(request)));
    }

    @Override
    @Validatable
    @PostMapping(value = "/get_value")
    public String getValue(String code) {
        return dictInitialize.getValue(code);
    }

    @PostMapping(value = "/list")
    public Result<List<DictDTO>> listDict(@RequestBody ListDictRequest request) {
        return Result.success(DictConverter.toDTO(dictService.listDict(DictConverter.toQuery(request))));
    }

    @PostMapping(value = "/count")
    public Result<Integer> countDict(@RequestBody ListDictRequest request) {
        return Result.success(dictService.countDict(DictConverter.toQuery(request)));
    }

    @PostMapping(value = "/page")
    public Result<Page<DictDTO>> pageDict(@RequestBody ListDictRequest request) {
        DictQuery query = DictConverter.toQuery(request);
        List<DictDTO> list = DictConverter.toDTO(dictService.listDict(query));
        int count = dictService.countDict(query);
        return Result.success(new Page<>(list, count));
    }

    @PostMapping(value = "/get_item")
    @Override
    public Result<ListDictItemResponse> getDictItem(@RequestBody GetDictByCodeRequest request) {
        if (!StringUtils.hasText(request.getDictGroupCode())) {
            return Result.ofBadRequest("字典分组编码不能为空");
        }
        if (!StringUtils.hasText(request.getDictCode())) {
            return Result.ofBadRequest("字典编码不能为空");
        }
        return Result.success(dictService.getDictItem(request));
    }

    @PostMapping(value = "/list_item")
    @Override
    public Result<List<ListDictItemResponse>> listDictItem(@RequestBody ListDictItemRequest request) {

        return Result.success(dictService.listDictItem(request));
    }

    @PostMapping(value = "/list_item_by_parent")
    public Result<List<ListDictItemResponse>> listDictItemByParent(@RequestBody ListDictItemRequest request) {
        return Result.success(dictService.listDictItemByParent(request));
    }

    @Validatable
    @PostMapping(value = "/list_dict_property")
    public Result<List<DictPropertyDTO>> listDictProperty(@RequestBody GetDictRequest request) {
        return Result.success(dictService.listDictProperty(request));
    }

    @PostMapping(value = "/list_dict_properties")
    public Result<List<DictPropertyDTO>> listDictProperties(@RequestBody GetDictRequest request) {
        return Result.success(dictService.listDictProperties(request));
    }

    @Validatable
    @PostMapping(value = "/list_tree_item")
    public Result<List<TreeItem>> listDictTreeItem(@RequestBody ListDictTreeItemRequest request) {
        List<ListDictItemResponse> listDictItemResponseList = dictService.listDictItem(ListDictItemRequest.builder()
                .dictGroupCode(request.getDictGroupCode())
                .parentDictId(request.getParentDictId())
                .withProperty(false)
                .build());
        if (!CollectionUtils.isEmpty(listDictItemResponseList)) {
            return Result.success(Tree.buildTreeItem(listDictItemResponseList,
                    e -> e.getSource().getDictId(),
                    e -> e.getSource().getParentDictId(),
                    e -> e == null || e == 0,
                    e -> e.getDictCode(),
                    e -> e.getDictValue(),
                    e -> e.getDictId()));
        }
        return Result.success(Collections.emptyList());
    }

    @Validatable
    @PostMapping(value = "list_tree_item_for_manage")
    public Result<List<TreeItem>> listDictTreeItemForManage(@RequestBody ListDictTreeItemRequest request) {
        List<ListDictItemResponse> listDictItemResponseList = dictService.listDictItem(ListDictItemRequest.builder()
                .dictGroupCode(request.getDictGroupCode())
                .parentDictId(request.getParentDictId())
                .withProperty(false)
                .build());
        if (!CollectionUtils.isEmpty(listDictItemResponseList)) {
            return Result.success(Tree.buildTreeItem(listDictItemResponseList,
                    e -> e.getSource().getDictId(),
                    e -> e.getSource().getParentDictId(),
                    e -> e == null || e == 0,
                    e -> e.getDictId().toString(),
                    e -> e.getDictValue()));
        }
        return Result.success(Collections.emptyList());
    }

    @PostMapping(value = "list_dict_group_item")
    public Result<List<StringKeyValue>> listDictGroupItem(@RequestBody ListDictGroupRequest request) {
        return Result.success(dictService.listDictGroupItem(request.getType()));
    }

    @PostMapping(value = "list_dict_group_item_all")
    public Result<List<TreeItem>> listDictGroupItemAll(@RequestBody ListDictGroupRequest request) {
        return Result.success(dictService.listDictGroupItemAll(request.getType()));
    }

    @PostMapping(value = "list_dict_group_item_by_group_code")
    public Result<List<TreeItem>> listDictGroupItemByGroupCode(@RequestBody ListDictItemRequest request) {
        return Result.success(dictService.listDictGroupItemByGroupCode(request));
    }

    @Data
    static class ListDictGroupRequest {
        private Integer type;
    }

}
